#include "GLTextureWindow.h"

GLTextureWindow::GLTextureWindow(QWidget* parent)
	: QOpenGLWidget(parent)
{
	this->resize(QSize(480, 480));
	this->setWindowTitle("纹理");
	this->setWindowIcon(QIcon("images/opencv.png"));
}
void GLTextureWindow::initializeGL() {
	this->initializeOpenGLFunctions();
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT);
	//创建VAO、VBO、EBO
	glGenBuffers(1, &VBO);
	glGenBuffers(1, &EBO);
	glGenVertexArrays(1, &VAO);

	//绑定VAO、VBO、EBO
	glBindVertexArray(VAO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);

	//将顶点数据和放入VBO和EBO
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	//指定顶点数据以何种形式排列(顶点坐标)
	glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(6);

	//指定颜色坐标以何种形式排列（颜色坐标）
	glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
	glEnableVertexAttribArray(8);

	//指定纹理坐标以何种形式排列
	glVertexAttribPointer(8, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
	glEnableVertexAttribArray(8);

	//创建纹理(第一个纹理)
	glGenTextures(1, &texture);
	//绑定纹理
	glBindTexture(GL_TEXTURE_2D, texture);
	//设置纹理环绕方式
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	//设置纹理过滤方式
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	//加载并生成纹理数据
	int width, height, mChannels;
	stbi_set_flip_vertically_on_load(true);
	//unsigned char* data = stbi_load("E:/tony/demo/visualstudio_workspace/QtForOpenCV4Tool/QtForOpenCV4Tool/bin/images/girl1.jpg", &width, &height, &mChannels, 0);
	unsigned char* data = stbi_load("E:/tony/demo/visualstudio_workspace/QtForOpenCV4Tool/QtForOpenCV4Tool/bin/images/similing_face.png", &width, &height, &mChannels, 0);
	if (data) {//将图像数据和纹理绑定
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,GL_UNSIGNED_BYTE, data);
		qDebug() << "图像的宽高：width=" << width << ",height=" << height << ",channels=" << mChannels;
		glGenerateMipmap(GL_TEXTURE_2D);
	}
	else {
		qDebug() << "加载图像数据失败";
	}
	stbi_image_free(data);


	//创建第二个纹理
	glGenTextures(1, &texture1);
	glBindTexture(GL_TEXTURE_2D, texture1);

	//设置纹理的环绕方式及过滤方式
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	//加载第二张图片
	data = stbi_load("E:/tony/demo/visualstudio_workspace/QtForOpenCV4Tool/QtForOpenCV4Tool/bin/images/images_cli.png", &width, &height, &mChannels, 0);
	if (data) {
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
		//glGenerateMipmap(GL_TEXTURE_2D);
	}
	else {
		qDebug() << "第二个纹理图像数据加载失败";
	}
	stbi_image_free(data);

	//启动gpu小程序
	GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
	QFile vertexShaderFile(":/QtForOpenCV4Tool/shader/texture.vert");
	if (!vertexShaderFile.open(QIODevice::ReadOnly)) {
		qDebug() << "Cannot open vertex shader file for reading";
	}
	QString verQStr = vertexShaderFile.readAll();
	std::string verStdStr = verQStr.toStdString();
	const char* vertexStr = verStdStr.c_str();
	qDebug() << "vertexStr-------------" << vertexStr;
	vertexShaderFile.close();
	glShaderSource(vertexShader, 1, &vertexStr, NULL);
	glCompileShader(vertexShader);
	//创建片元着色器
	QFile fragShaderFile(":/QtForOpenCV4Tool/shader/texture.frag");
	if (!fragShaderFile.open(QIODevice::ReadOnly)) {
		qDebug() << "Cannot open frag shader file for reading";
	}
	QString fragQStr = fragShaderFile.readAll();
	std::string fragStdStr = fragQStr.toStdString();
	const char* fragmentStr = fragStdStr.c_str();
	qDebug() << "fragmentStr-------------" << fragmentStr;
	unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragmentShader, 1, &fragmentStr, NULL);
	fragShaderFile.close();
	glCompileShader(fragmentShader);

	programId = glCreateProgram();
	//将着色器和显卡程序关联
	glAttachShader(programId, vertexShader);
	glAttachShader(programId, fragmentShader);
	glLinkProgram(programId);

	////设置sample2d变量的值，glUseProgram后设置才有效
	//GLint ourTextureLocation = glGetUniformLocation(programId, "ourTexture");
	//glUniform1i(ourTextureLocation, 0);

	//GLint ourTexture1Location = glGetUniformLocation(programId, "ourTexture1");
	//glUniform1i(ourTexture1Location, 1);

	//着色器使用后删除掉
	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);




}
void GLTextureWindow::resizeGL(int w, int h) {
	glViewport(0, 0, w, h);
}
void GLTextureWindow::paintGL() {
	//绑定vao(同时也就绑定了vbo和ebo)
	glBindVertexArray(VAO);

	//激活纹理绑定纹理
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, texture);

	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, texture1);
	glUseProgram(programId);
	//执行glUseProgram后设置才有效
	//设置sample2d变量的值
	GLint ourTextureLocation = glGetUniformLocation(programId, "ourTexture");
	glUniform1i(ourTextureLocation, 0);

	GLint ourTexture1Location = glGetUniformLocation(programId, "ourTexture1");
	glUniform1i(ourTexture1Location, 1);

	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
GLTextureWindow::~GLTextureWindow()
{
}
